#include "Room.h"
#include "RoomExistence.h"
#include <Game/World/Systems/RoomSystem.h>
#include <Game/World/Exit.h>
#include <Game/EntityManager.h>

using namespace Game;
using namespace World;
using namespace Components;
using namespace Totem;

Room::Room(Entity &owner, const T_String &type, Systems::RoomSystem &roomSystem)
	: Component(type), owner(owner), roomSystem(roomSystem), entityMgr(NULL), enterEventId("ENTER"), leaveEventId("LEAVE")
{
	exits = owner.addPropertyList<Exit*>("Exits");
	entities = owner.addPropertyList<Entity*>("Entities");

	owner.registerToEvent2<Entity&, const U32&>(enterEventId).connect(this, &Room::onEnter);
	owner.registerToEvent2<Entity&, const U32&>(leaveEventId).connect(this, &Room::onLeave);

	roomSystem.add(this);

	entityMgr = new EntityManager();
	Components::RoomExistence::RegisterToFactory(entityMgr->getFactory());
}

Room::~Room()
{
	if(entityMgr)
		delete entityMgr;
}

Entity &Room::create()
{
	Entity &entity = entityMgr->create();
	entity.addComponent<Room>("RoomExistence", *this);
	entities.push_back(&entity);
	return entity;
}

void Room::update(const F32 &dt)
{
	entityMgr->update(dt);
}

void Room::onEnter(Entity &entity, const U32 &direction)
{
	//Entity arrived from the direction
	entities.push_back(&entity);
	entityMgr->push_back(&entity);
}

void Room::onLeave(Entity &entity, const U32 &direction)
{
	//First, look up exit direction (must be valid)
	int exit_index = -1;
	for(U32 i = 0; i < exits.size(); i++)
	{
		if(exits[i].get()->getDirection() == direction)
		{
			exit_index = i;
			break;
		}
	}
	if(exit_index == -1)
	{
		//TODO: Should send event to entity that this exit is not a valid exit...
		return;
	}

	//Now we know exit is valid, so let's erase entity from this room before we move it, 
	//so that the entity doesn't exist in two rooms at once.
	for(U32 i = 0; i < entities.size(); i++)
	{
		if(entities[i].get()->getProperty<U32>("Id") == entity.getProperty<U32>("Id"))
		{
			entities.erase(i);
			break;
		}
	}

	//Make sure we also delete from the entity manager
	entityMgr->erase(&entity, false);

	//Make entity enter the new room
	exits[exit_index].get()->getTo().getOwner().sendEvent2<Entity&, const U32&>(enterEventId, entity, direction);
}
